package com.magicalcoder.pigeon.ioc;

import com.magicalcoder.pigeon.ioc.anotation.Resource;
import com.magicalcoder.pigeon.ioc.anotation.Service;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by hzhedongyu on 2017/6/12.
 */
public class BeanFactory {

    private Map<String,Object> beanMap = null;
    private Map<String,String> clazzValueMap = null;
    // objenesis是一个小型Java类库用来实例化一个特定class的对象 无需再提供默认构造器
    private static Objenesis objenesis = new ObjenesisStd(true);

    public void scanAllBeans(String pack) throws IllegalAccessException {
        //寻找所有注解
        Set<Class<?>> classSet = ScanPackage.getClasses(pack);

        beanMap = new HashMap<String,Object>(classSet.size());
        clazzValueMap = new HashMap<String,String>(classSet.size());
        if(classSet!=null && classSet.size()>0){
            for(Class<?> clazz : classSet){
                Service service = clazz.getAnnotation(Service.class);
                String value = null;
                if(service!=null){//是个bean

                    value = service.value();
                    if(value==null || "".equals(value)){
                        value = clazz.getSimpleName();
                    }
                }
                if(value!=null && !"".equals(value)){
                    if(beanMap.containsKey(value)){
                       throw new RuntimeException(String.format("bean %s 已经存在",value));
                    }
                    Object bean = objenesis.newInstance(clazz);
                    beanMap.put(value,bean);
                    clazzValueMap.put(clazz.getName(),value);
                }
            }
            //注解下的子属性

            for(Class<?> clazz : classSet){
                Object clazzBean = beanMap.get(clazzValueMap.get(clazz.getName()));
                Field[] fields = clazz.getDeclaredFields();
                if(fields!=null){
                    for(Field field:fields){
                        field.setAccessible(true);
                        Resource resource = field.getAnnotation(Resource.class);
                        String resourceName = null;
                        if(resource!=null){
                            resourceName = resource.value();
                        }
                        if(resourceName==null || "".equals(resourceName)){
                            resourceName = field.getName();
                        }
                        if(resourceName!=null){
                            //注入
                            Object bean = beanMap.get(resourceName);
                            field.set(clazzBean,bean);
                        }
                    }
                }
            }
        }
        PigeonBeanContainer.addMap(beanMap,clazzValueMap);
    }



    public Object getBean(Class<?> clazz){
        return beanMap.get(clazzValueMap.get(clazz.getName()));
    }
}
